#lang racket


(require "list.rkt")

(provide λ.
         λid
         cλ
         call
         λcall
         finally)


(define (λ. fn1 fn2 . fns)
  (define (λ.-rec f g)
    (λ args
      (f (apply g args))))
  (reducer λ.-rec (list* fn1 fn2 fns)))

(define λid (λ (x) x))

(define cλ
  (λ args
    (λ cargs
      (apply (first args) (append (rest args) cargs)))))

(define (call fn . args)
  (apply fn args))

(define-syntax λcall
  (syntax-rules ()
    ((_ proc)
     (λ args (apply proc args)))))

(define-syntax finally
  (syntax-rules ()
    ((_ body proc)
     (with-handlers ((exn? (λ (e) (proc) (raise e))))
       (begin0 body (proc))))))